package com.hexacta.hrs.web.struts.actions.feedbacks;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.struts2.interceptor.validation.SkipValidation;

import com.hexacta.hrs.domain.feedback.FeedbackPeriod;
import com.hexacta.hrs.services.employee.EmployeeService;
import com.hexacta.hrs.services.feedbacks.FeedbackPeriodService;
import com.hexacta.hrs.services.feedbacks.PeriodService;
import com.hexacta.hrs.services.person.PersonService;
import com.opensymphony.xwork2.ActionSupport;

public class ImportFinalResultsAction extends ActionSupport {

    private Workbook workbook;

    // private FinalResultsRowData rowData;

    private PersonService personService;

    private EmployeeService employeeService;

    private FeedbackPeriodService feedbackPeriodService;

    private File upload; // The actual file

    private String uploadContentType;// The content type of the file

    private String uploadFileName;// The uploaded file name and path

    private String fileCaption;// The caption of the file entered by user.

    private String successMessage = "";

    private InputStream reportStream;

    private String INCOMPLETE = "incomplete";

    private PeriodService periodService;

    // private Sheet aux;

    /* Actions */

    @Override
    public String execute() throws Exception {

        return SUCCESS;

    }

    @SkipValidation
    public String uploadFinalResults() throws Exception {
        try {
            if (!uploadContentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
                addFieldError("upload", "The file should be a Microsoft Office 2007 Excel Worksheet or above.");
                return SUCCESS;
            }

            workbook = new XSSFWorkbook(upload.getAbsolutePath());
        } catch (Exception e) {
            addFieldError("upload", "The file is not select, or is empty.");
            return SUCCESS;
        }
        Sheet sheet = workbook.getSheet("Evaluaciones");

        if (sheet == null) {
            addFieldError("upload", "The worksheet should have a sheet named Evaluaciones containing the information.");
            return SUCCESS;
        }

        int encontrados = 0;
        ArrayList<Integer> lista = new ArrayList<Integer>();

        FinalResultsRowData rowData;

        Map<Integer, String> errMap = new HashMap<Integer, String>();
        for (int i = 2; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);

            if (row == null) {
                continue;
            }

            rowData = new FinalResultsRowData(employeeService, periodService, row);

            if (rowData.getEmployee() == null) {
                errMap.put(i, "Employee not Found");
                continue;
            }

            if (rowData.getNewFinalBand() == null) {
                errMap.put(i, "Job Function not Found");
                continue;
            }

            FeedbackPeriod currentPeriod = rowData.getEmployee().getCurrentFeedbackPeriod();

            if (currentPeriod == null) {
                errMap.put(i, "There is no current period for this employee.");
                continue;
            }

            if (!currentPeriod.getPeriod().equals(rowData.getPeriod())) {
                errMap.put(i, "Invalid period. Should be " + currentPeriod.getPeriod());
                continue;
            }

            currentPeriod.setNewFinalBand(rowData.getNewFinalBand());
            currentPeriod.setNewFinalPosition(rowData.getNewFinalPosition());
            currentPeriod.setNewCommitment(rowData.getNewCommitment());
            currentPeriod.setNewPerformance(rowData.getNewPerformance());

            feedbackPeriodService.update(currentPeriod);

            encontrados++;
            lista.add(i);
            System.out.println("Row Number: " + row.getRowNum());
        }

		if (errMap.isEmpty()){
			setSuccessMessage("The file was uploaded successfully");
			return SUCCESS;
		} else {
			try {
				ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
				setErrors(sheet, errMap);
				removeMigratedRows(lista, sheet);
				workbook.write(byteArray);
				byteArray.close();

				reportStream = new ByteArrayInputStream(byteArray.toByteArray());
				return INCOMPLETE;
			} catch (Exception e) {
				ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
				reportStream = new ByteArrayInputStream(byteArray.toByteArray());
				addFieldError("upload", "The file have an error. Please check it if all the fields are complete.");
				return SUCCESS;
			}
		}
    }

    /* Private methods */

    /**
     * @param aux
     * @param errMap
     */
    private void setErrors(final Sheet sheet, final Map<Integer, String> errMap) {

        sheet.getRow(1).createCell(19).setCellValue("Error de importaci�n");

        for (int i = 2; i <= sheet.getLastRowNum(); i++) {
            sheet.getRow(i).createCell(19).setCellValue(errMap.get(i));
        }
    }

    private void removeMigratedRows(final ArrayList<Integer> lista, final Sheet aux) {

        System.out.println("LISTA TAMA�O " + lista.size());
        int cambia = aux.getLastRowNum();

        for (int i = lista.size() - 1; i >= 0; i--) {
            aux.getRow(lista.get(i)).getCell(18).setCellValue(aux.getRow(cambia).getCell(18).getStringCellValue());
            if (aux.getRow(cambia).getCell(17).getCellType() == Cell.CELL_TYPE_STRING) {
                aux.getRow(lista.get(i)).getCell(17).setCellValue(aux.getRow(cambia).getCell(17).getStringCellValue());
                aux.getRow(lista.get(i)).getCell(16).setCellValue(aux.getRow(cambia).getCell(16).getStringCellValue());
                aux.getRow(lista.get(i)).getCell(14).setCellValue(aux.getRow(cambia).getCell(14).getStringCellValue());
            } else if (aux.getRow(cambia).getCell(17).getCellType() == Cell.CELL_TYPE_FORMULA) {
                aux.getRow(lista.get(i)).getCell(17).setCellValue(aux.getRow(cambia).getCell(17).getCellFormula());
                aux.getRow(lista.get(i)).getCell(16).setCellValue(aux.getRow(cambia).getCell(16).getCellFormula());
                aux.getRow(lista.get(i)).getCell(14).setCellValue(aux.getRow(cambia).getCell(14).getCellFormula());
            }
            aux.getRow(lista.get(i)).getCell(15).setCellValue(aux.getRow(cambia).getCell(15).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(13).setCellValue(aux.getRow(cambia).getCell(13).getNumericCellValue());
            aux.getRow(lista.get(i)).getCell(12).setCellValue(aux.getRow(cambia).getCell(12).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(11).setCellValue(aux.getRow(cambia).getCell(11).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(10).setCellValue(aux.getRow(cambia).getCell(10).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(9).setCellValue(aux.getRow(cambia).getCell(9).getNumericCellValue());
            aux.getRow(lista.get(i)).getCell(8).setCellValue(aux.getRow(cambia).getCell(8).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(7).setCellValue(aux.getRow(cambia).getCell(7).getCellFormula());
            aux.getRow(lista.get(i)).getCell(6).setCellValue(aux.getRow(cambia).getCell(6).getDateCellValue());
            aux.getRow(lista.get(i)).getCell(5).setCellValue(aux.getRow(cambia).getCell(5).getDateCellValue());
            aux.getRow(lista.get(i)).getCell(4).setCellValue(aux.getRow(cambia).getCell(4).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(3).setCellValue(aux.getRow(cambia).getCell(3).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(2).setCellValue(aux.getRow(cambia).getCell(2).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(1).setCellValue(aux.getRow(cambia).getCell(1).getStringCellValue());
            aux.getRow(lista.get(i)).getCell(0).setCellValue(aux.getRow(cambia).getCell(0).getNumericCellValue());

            aux.removeRow(aux.getRow(cambia));

            System.out.println("SETEO : " + lista.get(i) + " POR : " + cambia);

            cambia--;
        }

    }

    /* Getters and setters */

    /**
     * @return the personService
     */
    public PersonService getPersonService() {
        return personService;
    }

    /**
     * @param personService
     *            the personService to set
     */
    public void setPersonService(final PersonService personService) {
        this.personService = personService;
    }

    /**
     * @return the employeeService
     */
    public EmployeeService getEmployeeService() {
        return employeeService;
    }

    /**
     * @param employeeService
     *            the employeeService to set
     */
    public void setEmployeeService(final EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    /**
     * @return the upload
     */
    public File getUpload() {
        return upload;
    }

    /**
     * @param upload
     *            the upload to set
     */
    public void setUpload(final File upload) {
        this.upload = upload;
    }

    /**
     * @return the uploadContentType
     */
    public String getUploadContentType() {
        return uploadContentType;
    }

    /**
     * @param uploadContentType
     *            the uploadContentType to set
     */
    public void setUploadContentType(final String uploadContentType) {
        this.uploadContentType = uploadContentType;
    }

    /**
     * @return the uploadFileName
     */
    public String getUploadFileName() {
        return uploadFileName;
    }

    /**
     * @param uploadFileName
     *            the uploadFileName to set
     */
    public void setUploadFileName(final String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

    /**
     * @return the fileCaption
     */
    public String getFileCaption() {
        return fileCaption;
    }

    /**
     * @param fileCaption
     *            the fileCaption to set
     */
    public void setFileCaption(final String fileCaption) {
        this.fileCaption = fileCaption;
    }

    public InputStream getReportStream() {
        return reportStream;
    }

    public void setReportStream(final InputStream reportStream) {
        this.reportStream = reportStream;
    }

    /**
     * @return the feedbackPeriodService
     */
    public FeedbackPeriodService getFeedbackPeriodService() {
        return feedbackPeriodService;
    }

    /**
     * @param feedbackPeriodService
     *            the feedbackPeriodService to set
     */
    public void setFeedbackPeriodService(final FeedbackPeriodService feedbackPeriodService) {
        this.feedbackPeriodService = feedbackPeriodService;
    }

    /**
     * @return the periodService
     */
    public PeriodService getPeriodService() {
        return periodService;
    }

    /**
     * @param periodService
     *            the periodService to set
     */
    public void setPeriodService(final PeriodService periodService) {
        this.periodService = periodService;
    }

    /**
     * @return the successMessage
     */
    public String getSuccessMessage() {
        return successMessage;
    }

    /**
     * @param successMessage
     *            the successMessage to set
     */
    public void setSuccessMessage(final String successMessage) {
        this.successMessage = successMessage;
    }

}
